﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using IDI.Studio.Core;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace IDI.Studio.Application.Interception
{
    public class TraceInterceptionBehavior : IInterceptionBehavior
    {
        private Stopwatch stopwatch = new Stopwatch();

        #region IInterceptionBehavior Members

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            string className = input.MethodBase.DeclaringType.Name;
            string methodName = input.MethodBase.Name;
            string generic = input.MethodBase.DeclaringType.IsGenericType ? string.Format("<{0}>", input.MethodBase.DeclaringType.GetGenericArguments().ToStringList()) : string.Empty;

            BeforeInvoke(className, generic, methodName, input.Arguments);

            IMethodReturn result = getNext()(input, getNext);

            AfterInvoke(className, generic, methodName, result);

            return result;
        }

        public bool WillExecute
        {
            get { return true; }
        }

        #endregion

        private void BeforeInvoke(string className, string generic, string methodName, IParameterCollection arguments)
        {
            string message = string.Format("BeforeInvoke {0}{1}.{2}({3})", className, generic, methodName, arguments.ToStringList());

            //Logger.Current.Info(message, rxId, methodName, new TimeSpan(), resourceId, string.Empty, string.Empty, string.Empty, userId, className);

            stopwatch.Reset();
            stopwatch.Start();
        }

        private void AfterInvoke(string className, string generic, string methodName, IMethodReturn result)
        {
            stopwatch.Stop();

            if (result.Exception == null)
            {
                string message = string.Format("AfterInvoke {0}{1}.{2}() return {3}", className, generic, methodName, result.ReturnValue);

                //Logger.Current.Info(message, rxId, methodName, stopwatch.Elapsed, string.Empty, string.Empty, string.Empty, string.Empty, userId, className);
            }
            else
            {
                //Logger.Current.Exception(result.Exception, rxId, methodName, resourceId, string.Empty, string.Empty, string.Empty, userId, className);
            }
        }
    }
}
